package ch.fusun.baron.basic.client.ui.player;

import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;

import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

import ch.fusun.baron.core.injection.Inject;
import ch.fusun.baron.core.injection.ReInjector;
import ch.fusun.baron.core.service.UserService;
import ch.fusun.baron.data.DataListener;
import ch.fusun.baron.data.DataUpdate;
import ch.fusun.baron.player.Dynasty;
import ch.fusun.baron.player.Player;
import ch.fusun.baron.player.api.MarriageService;
import ch.fusun.baron.player.api.PlayerService;

/**
 *
 */
public class MarriageProposalDialog extends TitleAreaDialog implements
        DataListener {

    private static final int MARRIAGE_AGE = 11;// SDZ should be configured
    @Inject
    private transient UserService userService;
    @Inject
    private transient PlayerService playerService;
    @Inject
    private transient MarriageService marriageService;
    private SelectionTable<Player> selectionTable;
    private SelectionTable<Player> otherSelectionTable;
    private SelectionTable<Entry<Player, Player>> proposalTable;

    /**
     * Kryo
     */
    public MarriageProposalDialog() {
        super(new Shell());
    }

    /**
     * @param parentShell
     *            the parent shell
     */
    public MarriageProposalDialog(Shell parentShell) {
        super(parentShell);
    }

    @Override
    protected Control createDialogArea(Composite parent) {
        ReInjector.getInstance().reInject(this);
        selectionTable = new SelectionTable<Player>(parent,
                PersonColumns.values());
        otherSelectionTable = new SelectionTable<Player>(parent,
                PersonColumns.values());

        playerService.addDataListener(this);
        marriageService.addDataListener(this);
        selectionTable.setInput(filter(playerService.getPlayers(userService
                .getUser())));
        otherSelectionTable
                .setInput(filterOthers(playerService.getAllPlayers()));

        proposalTable = new SelectionTable<Entry<Player, Player>>(parent,
                ProposalColumn.values());
        proposalTable.setInput(marriageService.getProposals());

        GridLayout layout = new GridLayout(2, false);
        parent.setLayout(layout);

        return parent;
    }

    @Override
    protected boolean isResizable() {
        return true;
    }

    @Override
    public void dataChanged(DataUpdate update) {
        getShell().getDisplay().asyncExec(new Runnable() {

            @Override
            public void run() {
                selectionTable.setInput(filter(playerService
                        .getPlayers(userService.getUser())));
                otherSelectionTable.setInput(filterOthers(playerService
                        .getAllPlayers()));
                proposalTable.setInput(marriageService.getProposals());
            }
        });
    }

    /**
     * @param allPlayers
     * @return
     */
    protected List<Player> filterOthers(List<Player> allPlayers) {
        List<Player> players = new LinkedList<Player>();
        Dynasty dynasty = playerService.getDynasty(userService.getUser());
        for (Player player : allPlayers) {
            if (!player.isDead() && player.getAge() > MARRIAGE_AGE
                    && !dynasty.equals(playerService.getDynasty(player))
                    && !marriageService.isMarried(player)) {
                players.add(player);
            }
        }
        return players;
    }

    /**
     * @param allPlayers
     * @return
     */
    protected List<Player> filter(List<Player> allPlayers) {
        List<Player> players = new LinkedList<Player>();
        for (Player player : allPlayers) {
            if (!player.isDead() && player.getAge() > MARRIAGE_AGE
                    && !marriageService.isMarried(player)) {
                players.add(player);
            }
        }
        return players;
    }

    @Override
    public boolean close() {
        playerService.removeDataListener(this);
        marriageService.removeDataListener(this);
        return super.close();
    }

    /**
     * @return The proposer
     */
    public Player getProposer() {
        return selectionTable.getSelection();
    }

    /**
     * @return The proposed to
     */
    public Player getProposedTo() {
        return otherSelectionTable.getSelection();
    }
}
